package com.qfedu.buy.server.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.qfedu.buy.common.config.RedisKeyConfig;
import com.qfedu.buy.common.config.SystemConfig;
import com.qfedu.buy.common.dto.SkillOrderAddDto;
import com.qfedu.buy.common.util.DateUtil;
import com.qfedu.buy.common.util.EncryptUtil;
import com.qfedu.buy.common.util.IdGenerator;
import com.qfedu.buy.common.util.RedissonUtil;
import com.qfedu.buy.common.vo.R;
import com.qfedu.buy.server.config.RabbimqConfig;
import com.qfedu.buy.server.dao.SkillGoodsDao;
import com.qfedu.buy.server.dao.SkillOrderDao;
import com.qfedu.buy.server.dto.SkillGoodsDetailDto;
import com.qfedu.buy.server.entity.SkillGoods;
import com.qfedu.buy.server.entity.SkillOrder;
import com.qfedu.buy.server.service.intf.SkillGoodsService;
import com.qfedu.buy.server.service.intf.SkillOrderService;
import org.redisson.api.RLock;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.UUID;

/**
 * @program: NeighborBuy
 * @description:
 * @author: Feri(邢朋辉)
 * @create: 2021-02-05 09:41
 */
@Service
public class SkillOrderServiceImpl implements SkillOrderService {
    @Autowired
    private SkillOrderDao dao;
    @Autowired
    private SkillGoodsDao goodsDao;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional //刚性事务
    public R saveOrderV1(int uid, SkillOrderAddDto dto) {
        //校验-
        if(uid>0 && dto!=null && dto.getSgid()>0 &&dto.getNum()>0){
            //校验是否限购
            //查询秒杀的商品
            SkillGoodsDetailDto goods=goodsDao.selectById(dto.getSgid());
            //防止恶意访问接口
            if(goods!=null) {
                //校验请购活动是否有效
                //验证秒杀活动是否开始
                if (DateUtil.eqtime(goods.getStime()) < 0 && DateUtil.eqtime(goods.getEtime()) > 0) {
                    //分布式锁
                    RLock rLock = RedissonUtil.getLock(RedisKeyConfig.SKILL_ORDER_LOCK + dto.getSgid(), RedisKeyConfig.SKILL_ACTIVITY_GOODS_TIME);
                    try {
                        if (rLock.isLocked()) {
                            //校验库存
                            if (goods.getStore() > dto.getNum()) {
                                //生成订单
                                SkillOrder order = new SkillOrder(IdGenerator.getInstance().nextId(),uid, dto.getSgid(), goods.getCurrprice()
                                        , dto.getPaytype(), dto.getNum(), SystemConfig.SKILL_ORDER_NOPAY,
                                        dto.getUaid(), goods.getCurrprice() * dto.getNum(), goods.getCurrprice() * dto.getNum());
                                if (dao.insert(order) > 0) {
                                    //扣减库存
                                    goodsDao.update(goods.getId(), dto.getNum());
                                    //记录订单流水
                                    //返回支付二维码
                                    return R.ok(dto.getPaytype());
                                }
                            }
                        }
                    } finally {
                        rLock.unlock();
                    }
                }
            }
        }
        return R.fail();
    }

    //优化：基于MQ的削峰填谷、基于Redis预扣减库存、基于Redis的缓存操作
    //可以考虑过滤前置
    @Override
    public R saveOrderV2(int uid,String path, SkillOrderAddDto dto) {
        //操作Redis--->MQ---->同步Mysql----订单超时
        //秒杀的商品 预存到Redis  特别是库存  后台管理系统
        if(!StrUtil.isEmptyIfStr(path) &&uid>0 && dto!=null && dto.getSgid()>0 &&dto.getNum()>0){
            //校验动态地址是否正确
            String ph=RedissonUtil.getStr(RedisKeyConfig.SKILL_ORDER_URL+uid+":"+dto.getSgid());
            if(path.equals(ph)) {
                //验证用户是否抢购过本商品
                if (RedissonUtil.isHave(RedisKeyConfig.SKILL_USERS)) {
                    if (RedissonUtil.checkSet(RedisKeyConfig.SKILL_USERS, uid + "-" + dto.getSgid())) {
                        //之前抢购过
                        return R.fail("亲，你已经购买过！");
                    } else {
                        //允许本次
                        SkillGoods goods = (SkillGoods) RedissonUtil.getHashObj(RedisKeyConfig.SKILL_GOODS, dto.getSgid() + "");
                        //分布式锁
                        RLock rLock = RedissonUtil.getLock(RedisKeyConfig.SKILL_ORDER_LOCK + dto.getSgid(), RedisKeyConfig.SKILL_ACTIVITY_GOODS_TIME);
                        try {
                            if (rLock.isLocked()) {
                                //校验库存
                                if (goods.getStore() > dto.getNum()) {
                                    //生成订单
                                    SkillOrder order = new SkillOrder(IdGenerator.getInstance().nextId(), uid, dto.getSgid(), goods.getCurrprice()
                                            , dto.getPaytype(), dto.getNum(), SystemConfig.SKILL_ORDER_NOPAY,
                                            dto.getUaid(), goods.getCurrprice() * dto.getNum(), goods.getCurrprice() * dto.getNum());
                                    //存储订单--Redis
                                    RedissonUtil.setStr(RedisKeyConfig.SKILL_ORDER + order.getId(), order);
                                    //扣减库存--预扣减-Redis
                                    goods.setStore(goods.getStore() - dto.getNum());
                                    RedissonUtil.setHash(RedisKeyConfig.SKILL_GOODS, dto.getSgid() + "", goods);
                                    //记录当前用户抢购过本商品
                                    RedissonUtil.setStr(RedisKeyConfig.SKILL_USERS, uid + "-" + dto.getSgid());
                                    //mq发送消息实现 数据同步 -1.数据同步 2.订单超时
                                    rabbitTemplate.convertAndSend(RabbimqConfig.ex_order, "", order.getId());
                                    return R.ok(dto.getPaytype());
                                }
                            }
                        } finally {
                            rLock.unlock();
                        }
                    }
                }
            }
        }
        return R.fail();
    }

    @Override
    @Transactional
    public boolean save(SkillOrder order) {
        if(order!=null && order.getId()>0){
            //保存订单
            dao.insert(order);
                //扣减库存
            goodsDao.update(order.getSgid(), order.getNum());
            return true;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean ordertimeout(long oid) {
        if(oid>0){
            SkillOrder order=dao.selectById(oid);
            if(order!=null){
                if(order.getFlag()==SystemConfig.SKILL_ORDER_NOPAY){
                    //订单超时
                    //更改订单状态为超时
                    dao.updateFlag(oid,SystemConfig.SKILL_ORDER_TIMEOUT);
                    //释放商品库存
                    goodsDao.updateAdd(order.getSgid(),order.getNum());
                    //释放优惠资源（优惠劵、积分）
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public R getpath(int uid, int gid) {
        if(uid>0 && gid>0){
            // 生成密文串码
            String path= EncryptUtil.sha(EncryptUtil.SHA1,uid+":"+gid+"-"+System.currentTimeMillis());
            RedissonUtil.setStr(RedisKeyConfig.SKILL_ORDER_URL+uid+":"+gid,path,RedisKeyConfig.SKILL_ORDER_URL_TIME);
            return R.ok(path);
        }
        return R.fail();
    }
}
